package com.roy.reversi.model;

import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JOptionPane;

import com.roy.reversi.listener.IReversiListener;

/**
 * 棋盘模型,保存一个8*8的二维数组
 *
 * @author Administrator
 * 
 */
public class Chessboard {
	
	public static final int CELLSIZE = 40;
	public static final int PIECESIZE = 36;
	public static final int GRIDNUMBER = 8;
	public static final int TOTAL_WIDTH = CELLSIZE * GRIDNUMBER + 1;
	public static final int TOTAL_HEIGHT = CELLSIZE * GRIDNUMBER + 1;
	
	public static final int NONE = 0;
	public static final int BLACK = 1;
	public static final int WHITE = 2;
	
	private int currentColor;
	
	private int[][] pieces;
	private IReversiListener listener;
	
	//向左、向右、向上、向下、左上、右上、右下、左下
	private int[][] moves = new int[][]{{-1, 0},{1, 0},{0,-1},{0, 1},
										{-1,-1},{1,-1},{1, 1},{-1,1} };
	
	public Chessboard() {
		pieces = new int[GRIDNUMBER][GRIDNUMBER];
		reset();
	}
	
	private void reset(){
		for (int x = 0; x < GRIDNUMBER; x++) {
			for (int y = 0; y < GRIDNUMBER; y++) {
				pieces[x][y] = 0;
			}
		}
		pieces[3][3] = WHITE;
		pieces[3][4] = BLACK;
		pieces[4][3] = BLACK;
		pieces[4][4] = WHITE;
		currentColor = BLACK;	//黑棋先行
	}
	
	public void newGame(){
		reset();
	}
	
	public void draw(Graphics g){
		int offset = (CELLSIZE - PIECESIZE)/2;
		
		for (int x = 0; x < GRIDNUMBER; x++) {
			for (int y = 0; y < GRIDNUMBER; y++) {
				//画棋盘
				g.setColor(Color.DARK_GRAY);
				g.drawRect(y * CELLSIZE, x * CELLSIZE, CELLSIZE, CELLSIZE);
				//画棋子
				if(pieces[x][y] == BLACK){
					g.setColor(Color.BLACK);
					g.fillOval(y * CELLSIZE + offset, x * CELLSIZE + offset, PIECESIZE, PIECESIZE);
				} else if(pieces[x][y] == WHITE){
					g.setColor(Color.WHITE);
					g.fillOval(y * CELLSIZE + offset, x * CELLSIZE + offset, PIECESIZE, PIECESIZE);
				}
			}
		}
	}
	
	public synchronized void pcPlayer(){
		while(currentColor != WHITE){
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		putOnFisrtCan();
	}
	
	public synchronized void notifyPc(){
		notify();
	}
	
	private boolean canPut(int color, int i, int j){
		//1.当前颜色是否我的颜色
		if(currentColor != color){
			listener.setInfo("还没轮到您下!");
			return false;
		}
		if(!canTurn(i, j, color)){
			listener.setInfo("此位置不能下!");
			return false;
		}
		return true;
	}
	
	private boolean canTurn(int x, int y, int color){
		boolean canput = false;
		if(pieces[x][y] == NONE){	//此位置为空
			int dirTurn = 0; 	//一个方向可以翻转的数量
			int dirTotal = 0;	//一个方向总的数量
			int nx,ny;	//新的坐标
			int oColor = getOppositeColor(color);
			
			for(int i = 0; i < moves.length; i++){
				nx = x + moves[i][0];
				ny = y + moves[i][1];
				
				dirTurn = 0;
				dirTotal = 0;
				
				while(nx >=0 && nx < 8 && 
						ny >=0 && ny < 8 && ( pieces[nx][ny]!=NONE ) ){
					dirTotal++ ;
					if(pieces[nx][ny] == oColor){
						dirTurn++ ;
					} else {
						break;
					}
					
					nx += moves[i][0];
					ny += moves[i][1];
				}
				
				if(dirTotal > dirTurn && dirTurn > 0){
					//可以翻转数量等于总数量。表示没有和下的颜色相同的棋子
					canput = true;
					break;
				}
			}
		}
		return canput;
	}
	
	private void doTurn(int x, int y, int color){
		List<int[]> turnList = new ArrayList<int[]>();
		
		int dirTurn = 0; 	//一个方向可以翻转的数量
		int dirTotal = 0;	//一个方向总的数量
		int nx,ny;	//新的坐标
		int oColor = getOppositeColor(color);
		
		for(int i = 0; i < moves.length; i++){
			turnList.clear();
			
			nx = x + moves[i][0];
			ny = y + moves[i][1];
			
			dirTurn = 0;
			dirTotal = 0;
			
			while(nx >=0 && nx < 8 && 
					ny >=0 && ny < 8 && ( pieces[nx][ny]!=NONE ) ){
				dirTotal++ ;
				if(pieces[nx][ny] == oColor){
					turnList.add(new int[]{nx, ny});
					dirTurn++ ;
				} else {
					break;
				}
				nx += moves[i][0];
				ny += moves[i][1];
			}
			
			if(dirTotal > dirTurn && dirTurn > 0){
				int[] temp;
				for(int j = 0; j < turnList.size(); j++){
					temp = turnList.get(j);
					pieces[temp[0]][temp[1]] = color;
				}
			}
			
		}
	}
	
	public void putOnFisrtCan(){
		label:
		for (int x = 0; x < GRIDNUMBER; x++) {
			for (int y = 0; y < GRIDNUMBER; y++) {
				if(canTurn(x, y, WHITE)){
					pcPut(WHITE, x, y);
					break label;
				}
			}
		}
	}
	
	private void pcPut(int color, int x, int y){
		pieces[x][y] = color;
		
		//1.翻棋
		doTurn(x, y, color);
		//2.判定对手是否能下，如果能下设置当前下的颜色
		setNextPlayer();
		listener.put();//界面刷新
	}
	
	public void put(int color, int posx, int posy){
		int y = posx/CELLSIZE;
		int x = posy/CELLSIZE;
		
		if(canPut(color, x, y)){
			pieces[x][y] = color;
			//1.翻棋
			doTurn(x, y, color);
			//2.判定对手是否能下，如果能下设置当前下的颜色
			setNextPlayer();
			listener.put();//界面刷新
			notifyPc();
		} else {
			//不能落子再这个位置
		}
	}
	
	private void setNextPlayer(){
		
		//如果下一个玩家有的下则设置
		int oColor = getOppositeColor(currentColor);
		if(playerCanPut(oColor)){ // 对手有棋子可以下
			currentColor = getOppositeColor(currentColor);
		} else if(!playerCanPut(currentColor)){// 自己也没有棋子下
			int bNum =getBlackNum();
			int wNum = getWhiteNum();
			String msg = null;
			if(bNum > wNum){
				msg = "黑棋赢！";
			} else if(bNum < wNum){
				 msg = "白棋赢！";
			} else {
				msg = "平局！";
			}
			JOptionPane.showMessageDialog(null, msg, "提示", JOptionPane.INFORMATION_MESSAGE);
		}
	}
	
	/**
	 * 玩家是否有下棋的地方
	 * @param color
	 * @return
	 */
	private boolean playerCanPut(int color){
		boolean canput = false;
		label:
			for (int x = 0; x < GRIDNUMBER; x++) {
				for (int y = 0; y < GRIDNUMBER; y++) {
					if(canTurn(x, y, color)){
						canput = true;
						break label;
					}
				}
			}
		return canput;
	}
	
	public void addListener(IReversiListener listener){
		this.listener = listener;
	}

	public int getCurrentColor() {
		return currentColor;
	}

	public void setCurrentColor(int currentColor) {
		this.currentColor = currentColor;
	}
	
	/**
	 * 取相对的颜色
	 * @param color
	 * @return
	 */
	private int getOppositeColor(int color){
		if(color == BLACK){
			return WHITE;
		}else{ 
			return BLACK;
		}
	}
	
	public int getWhiteNum(){
		int num = 0;
		for (int x = 0; x < GRIDNUMBER; x++) {
			for (int y = 0; y < GRIDNUMBER; y++) {
				if(pieces[x][y] == WHITE){
					num++ ;
				}
			}
		}
		return num;
	}
	
	public int getBlackNum(){ 
		int num = 0;
		for (int x = 0; x < GRIDNUMBER; x++) {
			for (int y = 0; y < GRIDNUMBER; y++) {
				if(pieces[x][y] == BLACK){
					num++ ;
				}
			}
		}
		return num;
	}
	
	public String getCurPlayer(){
		if(currentColor == BLACK){
			return "黑棋";
		} else {
			return "白棋";
		}
	}
	
}
